import EntityMng from "../Entities/EntityMng"
// import Connector from "../Entities/Connector";
import Avatar from "../Entities/Avatar";
import Room from "../Entities/Room";


import { HubConnectionBuilder, HubConnection, HttpTransportType, HubConnectionState } from '../libs/signalr/signalr';
import LanguageMng from "./LanguageMng";
import FireBaseMgr from "./FireBaseMgr";
import LogicConfigTs from "../Utils/LogicConfigTs";
import GameLogicUtilTs from "../Utils/GameLogicUtilTs";
import RoomTypes from "../Static/RoomTypes";
// import { ASYNC } from "../libs/async/async"

class GameWS{

    constructor(){
        this.hubConnection = null
        this.entities = new Map()
        this.e_events = new Map()
        this._cb_create = null
        this._cb_modify = null
        this._cb_destroy = null
        this._cb_trigger = null
    }

    async connect (url) {
        cc.log("开始连接signalR")
        this.hubConnection = await new HubConnectionBuilder()
            .withUrl(url, HttpTransportType.WebSockets)
            .withAutomaticReconnect([0,2,2])
            .build();
        await this.hubConnection.start().catch(function (err) {
            cc.log("进入了connection的start的catch里")
            console.error(err.toString());

            cc.gg.gameCtl.showNoticeReconnect()
            // return this.connect(url)
        }.bind(this));
        GameLogicUtilTs.forceLogoutWs = false
        this.initEvents()
        this.initGlobalEvents()
    }

    async closeWs(){
        return await this.hubConnection.stop()
    }

    showNoWebDialog(){
        let title = LanguageMng.getSentence(3)
        let btnStr = LanguageMng.getSentence(57)
        let contentStr = LanguageMng.getSentence(169)
        let cb = function () {
            cc.log("游戏关闭")
            cc.game.end()
        }.bind(this)
        cc.gg.toastMgr.showDialogOneButton(title,btnStr,contentStr,cb)
    }

    getState(){
        return this.hubConnection.state
    }

    initEvents () {
        this.hubConnection.on('create', (en_class, props) => this.onCreateEntity(en_class, props));
        this.hubConnection.on('destroy', (id) => this.onDestroyEntity(id));
        this.hubConnection.on('modify', (id, props) => this.onModifyEvent(id, props));
        this.hubConnection.on("trigger", (id, name, params) => this.onTriggerEvent(id, name, params));
        this.hubConnection.on("kick", (reason) => this.onKickEvent(reason));
        this.hubConnection.on("notify", (type, args) => this.onNotifyEvent(type, args));

        this.hubConnection.onreconnecting(async (err) => {
            GameLogicUtilTs.needStopDispatching = true
            console.log("On reconnecting", err);
            cc.gg.dataMgr.clearData()
            let sceneName = cc.gg.logicUtil.getCurrentSceneName()
            if(sceneName === LogicConfigTs.SCENENAME_GAME_2 || sceneName === LogicConfigTs.SCENENAME_GAME_6){
                await cc.gg.toastMgr.showNetWaitting()
            }else {
                cc.log("与SOCKET断开，由于未处于游戏场景，不显示网络等待界面。")
            }

            // setTimeout(function () {
            //     console.log("reconnecting time is out of 20 seconds,now connection state is:",HubConnectionState.Disconnected)
            //     if(this.hubConnection.state == HubConnectionState.Disconnected){
            //         cc.gg.gameCtl.showNoticeReconnect()
            //     }
            // }.bind(this),20000)
        });

        this.hubConnection.onreconnected(async (connectionId) => {
            GameLogicUtilTs.needStopDispatching = true
            console.log("On reconnected", connectionId);

            await this.login(cc.gg.httpUtil.USER_TOKEN)

            cc.gg.toastMgr.removeNetWaitting()

            let sceneName = cc.gg.logicUtil.getCurrentSceneName()
            if(sceneName === LogicConfigTs.SCENENAME_GAME_2 || sceneName === LogicConfigTs.SCENENAME_GAME_6){
                cc.gg.dataMgr._roomDataWather = 0
                cc.find("Canvas").emit("msgwatcher_add",function () {
                    console.log("监听room是否已经收到")
                    if(cc.gg.dataMgr.room){
                        cc.gg.gameDataUtil.goToLobby(true)
                        return true
                    }
                    cc.gg.dataMgr._roomDataWather++
                    if(cc.gg.dataMgr._roomDataWather === 100){
                        console.log("重连之后已经update了100次，仍然没有监测到room，放弃监测，直接回到大厅")

                        cc.gg.gameDataUtil.goToLobby(true)
                        cc.gg.dataMgr._roomDataWather = null
                        return true
                    }
                    return false
                }.bind(this))
            }

            // cc.gg.tpgMgr.onGameReconnect(function () {
            //     cc.gg.toastMgr.removeNetWaitting()
            // })
        });

        this.hubConnection.onclose((error) => {
            cc.log("websocket连接关闭，state:",this.hubConnection.state)
            if(this.hubConnection.state === HubConnectionState.Disconnected){
                cc.gg.toastMgr.removeNetWaitting()

                if(!GameLogicUtilTs.forceLogoutWs)
                    cc.gg.gameCtl.showNoticeReconnect()
            }
        });
    }

    onCreateEntity(en_class, props) {
        console.log('Entity Created', en_class, props);
        let entity = EntityMng.create(en_class, props, this);
        this.entities.set(entity.id, entity);
        let event_cb = this.e_events.get('create');
        if (event_cb) event_cb(entity);
    }

    onDestroyEntity(id) {
        console.log('Entity Destroyed', id);
        let entity = this.entities.get(id);
        entity.onDestroy();
        this.entities.delete(id);
        let event_cb = this.e_events.get('destroy');
        if (event_cb) event_cb(entity);
    }

    onModifyEvent(id, props) {
        console.log('Entity Modified', id, props);
        let entity = this.entities.get(id);
        let keys = Object.keys(props);
        keys.forEach(key => {
            entity._serv_modify(key, props[key]);
            let event_cb = this.e_events.get('modify');
            if (event_cb) event_cb(entity, key, props[key]);
        });
    }

    onTriggerEvent(id, name, params) {
        console.log('Entity Trigger', id, name, params);
        if (!params) params = [];
        let entity = this.entities.get(id);
        entity._serv_trigger(name, params);
        let event_cb = this.e_events.get('trigger');
        if (event_cb) event_cb(entity, name, params);
    }

    //玩家被踢掉
    //1金币不足 3账号被顶掉
    onKickEvent(reasonNum){
        cc.log("收到kick消息：",reasonNum)
        if(reasonNum === 1){
            cc.gg.logicUtil.onKickSinceCoinNotEnough()
        }else if(reasonNum === 3){
            cc.gg.logicUtil.showKickByReplace()
        }
    }

    onNotifyEvent(type, args){
        console.log('Entity Notify', type, args);
        cc.gg.toastMgr.showScroll(null , {type , args})
    }

    //: 'create' | 'modify' | 'trigger' | 'destroy'
    onEntityEvent(key, cb) {
        this.e_events.set(key, cb);
    }

    onMsg (msg) {
        switch (msg.type) {
            case cc.gg.enumConfig.MSG_TYPE.CREATE: {
                let entity = EntityMng.create(msg.data.en_class, msg.id, msg.data.props);
                this.entities.set(msg.id, entity);
                let event_cb = this._cb_create
                if (event_cb) event_cb(entity);
                break;
            }
            case cc.gg.enumConfig.MSG_TYPE.DESTROY: {
                let entity = this.entities.get(msg.id);
                this.entities.delete(msg.id);
                let event_cb = this._cb_destroy
                if (event_cb) event_cb(entity);
                break;
            }
            case cc.gg.enumConfig.MSG_TYPE.MODIFY: {
                let entity = this.entities.get(msg.id);
                entity._serv_modify(msg.data.name, msg.data.value);
                let event_cb = this._cb_modify
                if (event_cb) event_cb(entity, msg.data.name, msg.data.value);
                break;
            }
            case cc.gg.enumConfig.MSG_TYPE.TRIGGER: {
                let entity = this.entities.get(msg.id);
                entity._serv_trigger(msg.data.name, msg.data.params);
                let event_cb = this._cb_trigger
                if (event_cb) event_cb(entity, msg.data.name, msg.data.params);
                break;
            }
            case cc.gg.enumConfig.MSG_TYPE.HEART_BEAT:{
                //todo donothing
                break
            }
            case -1:{
                cc.error("错误信息：",msg.data)
                break
            }
            default:
                console.log('不支持的消息类型', msg.type);
        }
    }

    initGlobalEvents () {
        this.e_events.set('create',(entity) => {
            cc.logws(`==========Entity created:::[${entity.en_class()},ID: ${entity.id}]`);

            if (entity instanceof Room) {
                cc.gg.dataMgr.room = entity
                cc.gg.dataMgr._roomObj = {id:entity.mode,type:RoomTypes.POINTS}
                entity.onCreate()
                let gameMgr = cc.find("Canvas").getComponent("GameMgrBase")//因为是先读取场景再进入房间，所以这里一定能得到
                entity.initRoom(gameMgr)
                entity.startRoom()
                // entity.openRoom(cc.gg.dataMgr.room.mode,cc.gg.tpgMgr)
            }

            if (entity instanceof Avatar) {
                cc.find("Canvas").emit("msgwatcher_add",function () {
                    if(cc.gg.dataMgr.room){
                        entity.initUser()
                        cc.gg.dataMgr.users[entity.id] = entity
                        cc.log("users:",cc.gg.dataMgr.users)
                        cc.find("Canvas/UIManager").emit("ui_update_seat_user",entity)
                        return true
                    }
                    return false
                }.bind(this))
            }
        })

        this.e_events.set('modify',(entity,key,value) => {
            console.log(`==========Modify event from Entity[${entity.en_class()}, ID: ${entity.id}], Property: [Key: ${key}], Value: ${value}`);
        })


        this.e_events.set('trigger',(entity,key,value) => {
            console.log(`==========Trigger event from Entity[${entity.en_class()}, ID: ${entity.id}], Property: [Key: ${key}], Value: ${value}`);
        })

        this.e_events.set('destroy',(entity,key,value) => {
            console.log(`==========Entity destroyed:::[${entity.en_class()},ID: ${entity.id}]`);
            if (entity instanceof User) {
                entity.onDestroy()
            }

            if (entity instanceof Room) {
                entity.onDestroy()
            }
        })
    }

    // async trigger(name, params) {
    //     return this.send({
    //         type:cc.gg.enumConfig.MSG_TYPE.TRIGGER,
    //         // id:null,
    //         data:{ name, params }
    //     });
    // }

    trigger(name, params) {
        if (!this.hubConnection || this.hubConnection.state !== HubConnectionState.Connected) {
            console.error("网络连接状态错误");
            return;
        }
        if (!params) params = [];
        return this.hubConnection.invoke(name, ...params);
    }

    send (msg) {
        let _msg = JSON.stringify(msg);
        return this.hubConnection.send(_msg);
    }

    disconnect() {
        this.hubConnection.close(1000, '主动关闭');
    }

    async findRoom(type, mode, joker) {
        console.log('正在寻找房间...');
        let code = await this.trigger('findRoom', [type, mode, joker])
        if (code !== 0) {
            // 1=没有登陆 2=已经在房间里 3=type值错误 4=mode值错误 5=金币不足
            console.log('寻找房间失败， Code:', code);
            return code;
        }
        console.log(`寻找房间成功`);
        return code;
    }

    async login(token){
        // login的错误码 1=token无效 2=已经登陆
        // cc.logfl("signalr:login,token is:",token)
        return this.trigger("login", [token]);
    }

};

export default new GameWS();
// GameWS._instance = null;
// GameWS.getInstance = function () {
//     if(!GameWS._instance){
//         GameWS._instance = new GameWS()
//     }
//     return GameWS._instance;
// }
// module.exports = GameWS;